package com.base.core.util;

import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigDecimal;

import javax.imageio.ImageIO;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 图片处理类，主要用于图片缩放
 * 
 * @author yanwz
 *
 */
public class ImageUtil {
    private static final Logger log = LoggerFactory.getLogger(ImageUtil.class);

    /**
     * 等比缩放图片（为防止变形，采用先等比缩放，再截取） 宽度或高度为0时，将按照不为0的进行等比缩放
     * 
     * @param input
     *            输入流
     * @param width
     *            宽度
     * @param height
     *            高度
     * @return
     * @throws Exception
     */
    public static BufferedImage cutImage(BufferedImage input, int width, int height) {
        BufferedImage om = null;
        int originalW = input.getWidth();
        int originalH = input.getHeight();
        boolean flag = false;
        if (width == 0 || height == 0) {
            width = (width == 0) ? (int) ((height * originalW * 1.0f) / originalH) : width;
            height = (height == 0) ? (int) ((width * originalH * 1.0f) / originalW) : height;
            flag = true;
        }
        if (flag) {// 等比缩放
            om = zoomImage(input, width, height);
        } else {
            float WRatio = (float) originalW / width;
            float HRatio = (float) originalH / height;
            int e = Float.compare(getPrecision(WRatio, 2), getPrecision(HRatio, 2));
            if (e == 0) {// 比例相同
                om = zoomImage(input, width, height);
            } else {
                // 判断按（宽或高）缩放
                int nH = (int) (width * originalH * 1.0F / originalW);
                int nW = (int) (height * originalW * 1.0F / originalH);
                if (nW > width) {
                    nH = height;
                }
                if (nH > height) {
                    nW = width;
                }
                // 按比例缩放
                BufferedImage temp = zoomImage(input, nW, nH);
                // 截取
                om = temp.getSubimage(0, 0, width, height);
                temp = null;
            }
        }
        return om;
    }

    /**
     * 图片缩放
     * 
     * @param im
     *            原始图片流
     * @param ratio
     *            缩放比
     * @return
     */
    public BufferedImage zoomImage(BufferedImage im, float ratio) {
        BufferedImage result = null;
        try {
            int width = im.getWidth();
            int height = im.getHeight();
            int toWidth = (int) (width * ratio);
            int toHeight = (int) (height * ratio);
            result = zoomImage(im, toWidth, toHeight);
        } catch (Exception e) {
            log.error("创建缩略图发生异常" + e.getMessage());
        }
        return result;
    }

    /**
     * 图片缩放
     * 
     * @param im
     *            原始图片流
     * @param w
     *            宽度
     * @param h
     *            高度
     * @return
     */
    public static BufferedImage zoomImage(BufferedImage source, int targetW, int targetH) {
        int type = source.getType();
        BufferedImage target = null;
        double sx = (double) targetW / source.getWidth();
        double sy = (double) targetH / source.getHeight();
        target = new BufferedImage(targetW, targetH, type);
        Graphics2D g = target.createGraphics();
        g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        g.drawRenderedImage(source, AffineTransform.getScaleInstance(sx, sy));
        g.dispose();
        return target;
    }

    /**
     * 浮点数四舍五入
     * 
     * @param a
     * @param pre
     *            小数位数
     * @return
     */
    private static float getPrecision(float a, int pre) {
        BigDecimal bd_a = new BigDecimal(a);
        return bd_a.setScale(pre, BigDecimal.ROUND_HALF_UP).floatValue();
    }

    public static void createOutputStreamFromBufferedImage(BufferedImage im, String ext, ByteArrayOutputStream output)
            throws IOException {
        ImageIO.write(im, ext, output);
    }

    public static BufferedImage getBufferedImageFromOutputStream(ByteArrayOutputStream outputStream) throws IOException {
        return ImageIO.read(new ByteArrayInputStream(outputStream.toByteArray()));
    }

    public static ByteArrayInputStream getByteArrayInputStreamFromBufferedImage(ByteArrayOutputStream outputStream)
            throws IOException {
        return new ByteArrayInputStream(outputStream.toByteArray());
    }
}